import 'package:df/page/login/lark/app_access_token.dart';
import 'package:df/page/login/lark/refresh_access_token.dart';
import 'package:df/page/login/lark/user_access_token.dart';
import 'package:df/page/login/lark/user_info.dart';
import 'package:df/page/splash/splash_page.dart';
import 'package:df/utils/logger_utils.dart';
import 'package:dio/dio.dart';
import 'dart:async';
import 'package:lark_auth/lark_auth.dart';
import 'package:flutter/foundation.dart';
import 'package:df/generated/l10n.dart';

///TODO 后端不肯做授权码之后的事情，导致的SB方案。
/// 飞书登录回调。
typedef LarkCallback = Function(Lark response);
const int kCodeLarkSuccess = 0;
const int kCodeLarkUnknownError = -1;
const int kCodeLarkError = 1;
class LarkConstant {
  //中文
  static const String kLanguageZh = 'zh';
  //越南语
  static const String kLanguageVi = 'vi';
  //西班牙语
  static const String kLanguageEs = 'es';
  //德语
  static const String kLanguageDe = 'de';
  //英语
  static const String kLanguageEn = 'en';
  //泰语
  static const String kLanguageTh = 'th';
  //法语
  static const String kLanguageFr = 'fr';
  //印地语
  static const String kLanguageHi = 'hi';
  //意大利语
  static const String kLanguageIt = 'it';
  //印度尼西亚语
  static const String kLanguageId = 'id';
  //韩语
  static const String kLanguageKo = 'ko';
  //俄语
  static const String kLanguageRu = 'ru';
  //日语
  static const String kLanguageJa = 'ja';
  //葡萄牙语
  static const String kLanguagePt = 'pt';


  //飞书(国内)
  static const String kServerFeishu = 'Feishu';
  //飞书
  static const String kServerLark = 'Lark';

}
/// 飞书登录回调接口。
class Lark {
  Lark._(this.code, this.msg, this.data);

  final int code;
  final String msg;
  final String? data;
}

/// 【飞书1/5】移动应用拉起飞书授权登录(获取授权码)。https://open.feishu.cn/document/common-capabilities/sso/mobile-app/mobile-app-overview
///
/// https://juejin.cn/post/7031538527955320862
/// [language] 语言。
/// [callback] 请求结果回调。
/// Returns 飞书授权对象。
/// [StateError] 异常说明。[Point.polar()]
/// [postUserAccessToken3] 涉及到方法。
/// [Lark.code] 涉及到属性。
/// Example/例子:
/// ```dart
/// Future<LarkAuth?> larkAuth = larkLogin("zh", callback);
/// print(larkAuth); // Output/输出: Instance of 'Future<LarkAuth?>'
/// ```
Future<LarkAuth?> larkLogin(String language, LarkCallback callback) async {
  LarkAuth larkAuth = LarkAuth();
  String server = LarkConstant.kServerFeishu;
  List<String> scopes = [];
  // approval:approval                  查看、创建、更新、删除审批应用相关信息
  // approval:approval:readonly         访问审批应用
  // attendance:task                    写入打卡数据
  // calendar:calendar                  更新日历及日程信息
  // calendar:calendar:readonly         获取日历、日程及忙闲信息
  // calendar:timeoff                   创建或删除请假日程
  // im:message                         获取与发送单聊、群组消息
  // im:message.group_at_msg:readonly   接收群聊中@机器人消息事件
  // im:message.p2p_msg:readonly        读取用户发给机器人的单聊消息
  // contact:contact                    更新通讯录
  // bitable:app                        查看、评论、编辑和管理多维表格
  // contact:contact:readonly_as_app    以应用身份读取通讯录
  // contact:user.employee_id:readonly  获取用户 User ID
  // contact:user.id:readonly           通过手机号或邮箱获取用户 ID
  scopes.add("contact:user.employee_id:readonly");
  scopes.add("contact:user.id:readonly");
  // https://open.feishu.cn/document/common-capabilities/sso/mobile-app/sdk
  Future<String?> responseVerifyCode = larkAuth.startSSOVerify(//TODO 1
    appId: "cli_a5038d79f9a9d013",//设置为在开发者后台-【凭证和基础信息】中申请的app_id
    server: server,//设置飞书服务器，必须为Feishu
    challengeMode: true,//设置是否使用挑战码模式（适用于无服务端的移动应用），默认为false
    scopeList: scopes,//设置用户必须授予的权限，需要在应用已向租户申请的权限范围内，超出的会被忽略；没有通过此参数传入的权限，用户可以选择不授权
    deviceId: Splash.packageName,//设置设备ID，用于相关问题的定位。如宿主有DeviceID系统，可通过此API设置；如果没有可不填，设置方法会返回生成的DeviceID，用户需保存DeviceID以供定位问题。DID长度限制为100位
    language: language,//没有安装飞书客户端的情况下，用于控制降级的H5页面的语言
  );
    // -1	状态码校验失败，非当前SDK请求的响应
    // -2	没有获得有效的授权码
    // -3	用户取消授权
    // -4	跳转飞书失败
    // -5	授权失败
    // -6	请求参数错误
  
  responseVerifyCode.then((authorizeCode) {
    if(authorizeCode != null && authorizeCode.isNotEmpty) {
      LogUtils.v("【飞书登录】授权码= ${authorizeCode}");
      switch(authorizeCode) {

      }

      Future<Response> responseAppAccessToken = postAppAccessToken2(authorizeCode);//TODO 2
      responseAppAccessToken.then((response2) {//应该处理网络请求异常情况
        if (kDebugMode) {
          LogUtils.d("【飞书登录】【获取 app_access_token】结果= ${response2}");
        }
        LogUtils.d("【飞书登录】【Token】结果= ${response2.runtimeType}");
        LogUtils.d("【飞书登录】【Token】结果= ${response2.data.runtimeType}");

        try {
          // 直接将 Response.data 转换为 Post 对象
          AppAccessToken appAccessTokenObj = AppAccessToken.fromJson(response2.data);
          int appCode = appAccessTokenObj.code;
          String appMsg = appAccessTokenObj.msg;
          String appAccessToken = appAccessTokenObj.appAccessToken;
          if(appCode == kCodeLarkSuccess) {//错误码：https://open.feishu.cn/document/server-docs/api-call-guide/generic-error-code
            LogUtils.d("【飞书登录】【Token】应用访问凭证= ${appAccessToken}");
            if(appCode == kCodeLarkSuccess) {

              Future<Response> responseUserAccessToken = postUserAccessToken3(appAccessToken, authorizeCode);//TODO 3
              responseUserAccessToken.then((response3) {
                if (kDebugMode) {
                  LogUtils.d("【飞书登录】【获取 user_access_token】结果= ${response3}");
                }
                LogUtils.d("【飞书登录】【获取 user_access_token】结果类型= ${response3.runtimeType}");
                LogUtils.d("【飞书登录】【获取 user_access_token】结果数据= ${response3.data.runtimeType}");

                UserAccessToken userAccessTokenObj = UserAccessToken.fromJson(response3.data);
                int userCode = userAccessTokenObj.code;
                String userMsg = userAccessTokenObj.msg;
                if(userCode == kCodeLarkSuccess) {
                  AccessToken userAccessToken = userAccessTokenObj.data;
                  String unionId = userAccessToken.unionId;
                  String accessToken = userAccessToken.accessToken;
                  String refreshToken = userAccessToken.refreshToken;
                  LogUtils.d("【飞书登录】【Token】结果数据对象= ${userAccessToken}");
                  LogUtils.d("【飞书登录】【Token】结果用户统一Id= ${unionId}");
                  LogUtils.d("【飞书登录】【Token】user_access_token(用于获取用户资源)= ${accessToken}");
                  LogUtils.w("【飞书登录】【Token】refreshToken(用于获取用户资源)= ${refreshToken}");//刷新用户 access_token 时使用的 token
                  callback(Lark._(userCode, userMsg, unionId));

                  if (kDebugMode) {
                    if (false) {
                      Future<Response> responseUserInfo = getUserInfo4(accessToken);//TODO 4
                      responseUserInfo.then((response4) {
                        if (kDebugMode) {
                          LogUtils.w("【飞书登录】【获取 user_info】结果= ${response4}");
                        }
                        LogUtils.w("【飞书登录】【获取 user_info】结果类型= ${response4.runtimeType}");
                        LogUtils.w("【飞书登录】【获取 user_info】结果数据= ${response4.data.runtimeType}");
                        UserInfo userInfoObj = UserInfo.fromJson(response4.data);
                        int infoCode = userInfoObj.code;
                        String infoMsg = userInfoObj.msg;

                        if (false) {
                          if(infoCode == kCodeLarkSuccess) {
                            User user = userInfoObj.data;
                            String unionId = user.unionId;
                            LogUtils.w("【飞书登录】【Token】结果用户统一Id= ${unionId}");
                            callback(Lark._(kCodeLarkSuccess, infoMsg, unionId));
                          } else {
                            LogUtils.d("【飞书登录】【获取 user_info】错误码= ${infoCode}");
                            LogUtils.d("【飞书登录】【获取 user_info】错误描述= ${infoMsg}");
                            callback(Lark._(infoCode, infoMsg, null));
                          }
                        }

                      });
                    } else {
                      Future<Response> refreshAccessToken = postRefreshAccessToken5(appAccessToken, refreshToken);//TODO 5
                      refreshAccessToken.then((response5) {
                        if (kDebugMode) {
                          LogUtils.w("【飞书登录】【获取 refresh_access_token】结果= ${response5}");
                        }
                        LogUtils.w("【飞书登录】【获取 refresh_access_token】结果类型= ${response5.runtimeType}");
                        LogUtils.w("【飞书登录】【获取 refresh_access_token】结果数据= ${response5.data.runtimeType}");

                        RefreshAccessToken refreshAccessTokenObj = RefreshAccessToken.fromJson(response5.data);
                        int refreshCode = refreshAccessTokenObj.code;
                        String accessTokenMsg = refreshAccessTokenObj.message;
                        if(refreshCode == kCodeLarkSuccess) {
                          RefreshToken refreshToken = refreshAccessTokenObj.data;
                          String accessToken = refreshToken.accessToken;
                          LogUtils.w("【飞书登录】【Token】结果用户统一Id= ${accessToken}");
                        } else {
                          LogUtils.d("【飞书登录】【获取 refresh_access_token】错误码= ${refreshCode}");
                          LogUtils.d("【飞书登录】【获取 refresh_access_token】错误描述= ${accessTokenMsg}");
                        }
                      });
                    }
                  }
                } else {
                  LogUtils.d("【飞书登录】【获取user_access_token】错误码= ${userCode}");
                  LogUtils.d("【飞书登录】【获取user_access_token】错误描述= ${userMsg}");
                  callback(Lark._(userCode, userMsg, null));
                }
              });
            }

          } else {
            LogUtils.d("【飞书登录】【获取 app_access_token】错误码= ${appCode}");
            LogUtils.d("【飞书登录】【获取 app_access_token】错误描述= ${appMsg}");
            callback(Lark._(appCode, appMsg, null));
          }
        } catch (error) {
          LogUtils.d("【飞书登录】【反序列化】异常= ${error}");
          callback(Lark._(kCodeLarkUnknownError, S.current.lark, null));
        }
      });
    } else {
      return Lark._(kCodeLarkUnknownError, '授权码异常', null);
    }
  });

  return larkAuth;
}


/// 【飞书2/5】获取app_access_token。 https://open.feishu.cn/document/server-docs/authentication-management/access-token/app_access_token_internal
Future<Response> postAppAccessToken2(String code) async {
  // 创建 Dio 实例
  Dio dio = Dio();
  //debugDio(dio);

  // 定义请求头
  Map<String, dynamic> headers = {
    'Content-Type': 'application/json; charset=utf-8',
    'Authorization': 'Bearer ${code}',
  };
  // 构建 Options 对象
  Options options = Options(
    headers: headers,
  );

  // 构建请求体数据
  Map<String, dynamic> data = {
    'app_id': 'cli_a5038d79f9a9d013',
    'app_secret': 'uFyX0Ql21xVqlYOn03YQieZxK25iKNmj',//示例值："xMSldislSkdK"
  };

  // 发送 POST 请求
  return await dio.post(
    "https://open.feishu.cn/open-apis/auth/v3/app_access_token/internal",
    data: data,
    options: options,
  );

  /*返回值：
    {
    "app_access_token": "t-g104179M5SQD3RUOPNT6BDUYO4ZSUQOO6KGKUKOH",
    "code": 0,
    "expire": 7200,
    "msg": "ok",
    "tenant_access_token": "t-g104179M5SQD3RUOPNT6BDUYO4ZSUQOO6KGKUKOH"
    }
    */
}

///【飞书3/5】获取user_access_token。 https://open.feishu.cn/document/server-docs/authentication-management/access-token/create-2?appId=cli_a5038d79f9a9d013
Future<Response> postUserAccessToken3(String appAccessToken, String code) async {
  // 创建 Dio 实例
  Dio dio = Dio();

  // 定义请求头
  Map<String, dynamic> headers = {
    'Content-Type': 'application/json; charset=utf-8',
    'Authorization': 'Bearer ${appAccessToken}',
  };
  // 构建 Options 对象
  Options options = Options(
    headers: headers,
  );

  // 构建请求体数据
  Map<String, dynamic> data = {
    'grant_type': 'authorization_code',
    'code': code,// https://open.feishu.cn/document/server-docs/authentication-management/login-state-management/obtain-code
  };

  // 发送 POST 请求
  return await dio.post(
    "https://open.feishu.cn/open-apis/authen/v1/access_token",
    data: data,
    options: options,
  );
  /*
  {
  "code": 0,
  "data": {
    "access_token": "u-d_Mn6Nw0R6TE_vA8owg29P5k0Nw151pHPgG0lhg00HMu",
    "avatar_big": "https://s1-imfile.feishucdn.com/static-resource/v1/v2_93bf69bd-e201-4b87-8523-432c295a39cg~?image_size=640x640&cut_type=&quality=&format=image&sticker_format=.webp",
    "avatar_middle": "https://s1-imfile.feishucdn.com/static-resource/v1/v2_93bf69bd-e201-4b87-8523-432c295a39cg~?image_size=240x240&cut_type=&quality=&format=image&sticker_format=.webp",
    "avatar_thumb": "https://s1-imfile.feishucdn.com/static-resource/v1/v2_93bf69bd-e201-4b87-8523-432c295a39cg~?image_size=72x72&cut_type=&quality=&format=image&sticker_format=.webp",
    "avatar_url": "https://s1-imfile.feishucdn.com/static-resource/v1/v2_93bf69bd-e201-4b87-8523-432c295a39cg~?image_size=72x72&cut_type=&quality=&format=image&sticker_format=.webp",
    "email": "hehongdan@126.com",
    "en_name": "HeHongdan",
    "enterprise_email": "",
    "expires_in": 6900,
    "mobile": "+86180***7864",
    "name": "洪丹",
    "open_id": "ou_1de3878130faceaae57c4884277564f8",
    "refresh_expires_in": 2591700,
    "refresh_token": "ur-e_2Nm8j5d8qpqEuFMqk3Rw5k2NE151N9OwG04l000KRf",
    "tenant_key": "1044ee5a02d85758",
    "token_type": "Bearer",
    "union_id": "on_4ef6c0235db38923b0d6002c5fa39f0a",
    "user_id": "49b4ca75"
    },
    "msg": "success"
  }
  */
}

///【飞书4/5】获取用户身份信息。 https://open.feishu.cn/document/server-docs/authentication-management/login-state-management/get?appId=cli_a5038d79f9a9d013
@Deprecated("和后台配合实现时用到")
Future<Response> getUserInfo4(String userAccessToken) async {
  // 创建 Dio 实例
  Dio dio = Dio();
  debugDio(dio);

  // 定义请求头
  Map<String, dynamic> headers = {
    'Content-Type': 'application/json; charset=utf-8',
    'Authorization': 'Bearer ${userAccessToken}',
  };
  // 构建 Options 对象
  Options options = Options(
    headers: headers,
  );

  // 发送 POST 请求
  return await dio.get(
    "https://open.feishu.cn/open-apis/authen/v1/user_info",
    options: options,
  );
  /*
    {
    "code": 0,
    "data": {
        "avatar_big": "https://s3-imfile.feishucdn.com/static-resource/v1/v2_93bf69bd-e201-4b87-8523-432c295a39cg~?image_size=640x640&cut_type=&quality=&format=image&sticker_format=.webp",
        "avatar_middle": "https://s1-imfile.feishucdn.com/static-resource/v1/v2_93bf69bd-e201-4b87-8523-432c295a39cg~?image_size=240x240&cut_type=&quality=&format=image&sticker_format=.webp",
        "avatar_thumb": "https://s1-imfile.feishucdn.com/static-resource/v1/v2_93bf69bd-e201-4b87-8523-432c295a39cg~?image_size=72x72&cut_type=&quality=&format=image&sticker_format=.webp",
        "avatar_url": "https://s1-imfile.feishucdn.com/static-resource/v1/v2_93bf69bd-e201-4b87-8523-432c295a39cg~?image_size=72x72&cut_type=&quality=&format=image&sticker_format=.webp",
        "email": "hehongdan@126.com",
        "employee_no": "0019249167",
        "en_name": "HeHongdan",
        "enterprise_email": "",
        "mobile": "+86180***7864",
        "name": "洪丹",
        "open_id": "ou_1de3878130faceaae57c4884277564f8",
        "tenant_key": "1044ee5a02d85758",
        "union_id": "on_4ef6c0235db38923b0d6002c5fa39f0a",
        "user_id": "49b4ca75"
    },
    "msg": "success"
  }
    */
}

void debugDio(Dio dio) {
  // 添加拦截器，用于打印请求参数和返回值
  dio.interceptors.add(InterceptorsWrapper(
    onRequest: (RequestOptions options, RequestInterceptorHandler handler) {
      // 打印请求头
      print('【Dio】请求头: ${options.uri}\n${options.headers}');
      // 打印请求参数
      print('【Dio】请求参数: ${options.uri}\n${options.data}');

      // 继续处理请求
      return handler.next(options);
    },
    onResponse: (Response response, ResponseInterceptorHandler handler) {
      // 打印返回值
      print('【Dio】响应: ${response.requestOptions.uri}\n${response.data}');

      // 继续处理返回值
      return handler.next(response);
    },
    onError: (DioError e, ErrorInterceptorHandler handler) {
      // 打印错误信息
      print('【Dio】出错: ${e.requestOptions.uri}\n${e.message}');

      // 继续处理错误
      return handler.next(e);
    },
  ));
}



/// 【飞书5/5】刷新已过期的access_token。https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/authen-v1/oidc-refresh_access_token/create?appId=cli_a5038d79f9a9d013
@Deprecated("和后台配合实现时用到")
Future<Response> postRefreshAccessToken5(String appAccessToken, String refreshToken) async {
  // 创建 Dio 实例
  Dio dio = Dio();

  // 定义请求头
  Map<String, dynamic> headers = {
    'Content-Type': 'application/json; charset=utf-8',
    'Authorization': 'Bearer ${appAccessToken}',
  };
  // 构建 Options 对象
  Options options = Options(
    headers: headers,
  );

  // 构建请求体数据
  Map<String, dynamic> data = {
    'grant_type': 'refresh_token',
    'refresh_token': refreshToken,// https://open.feishu.cn/document/server-docs/authentication-management/access-token/create-2?appId=cli_a5038d79f9a9d013
  };

  // 发送 POST 请求
  return await dio.post(
    "https://open.feishu.cn/open-apis/authen/v1/oidc/refresh_access_token",
    data: data,
    options: options,
  );
  /*
  {
    "code": 0,
    "data": {
        "access_token": "u-fsfvKV5hF6lWIo8g5D0hHMg5jEz151VbN200lh4009Cy",
        "refresh_token": "ur-eB4FNBgKl0ZGfK5.Umxwkvg5jaFx51h1oi00glg00dDP",
        "token_type": "Bearer",
        "expires_in": 7200,
        "refresh_expires_in": 2592000,
        "scope": "auth:user.id:read"
    },
    "message": "success"
  }
  */
}


